import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;
import javax.swing.LookAndFeel;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import net.sf.stackwrap4j.datastructures.UsersByIdList;
import net.sf.stackwrap4j.entities.User;
import net.sf.stackwrap4j.exceptions.ParameterNotSetException;
import net.sf.stackwrap4j.http.HttpClient;
import net.sf.stackwrap4j.json.JSONException;

public class MainFrame extends JFrame {

    private AddUserDialog addUser;
    private RemoveUserDialog removeUser;
    private ReputationGraph repGraph;

    public MainFrame() throws IOException, JSONException, ParameterNotSetException {
        super("Reputation Graph Compare");
        repGraph = new ReputationGraph();
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        add(repGraph);
        createMenu();
        addUser = new AddUserDialog(this);
        removeUser = new RemoveUserDialog(this);
        pack();
        setVisible(true);
    }

    private void createMenu() {
        JMenuBar bar = new JMenuBar();
        JMenu fileMenu = new JMenu("File");
        JMenuItem addUserItem = new JMenuItem("Add User");
        final JCheckBox keyVilibleItem = new JCheckBox("Hide Key");
        keyVilibleItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                repGraph.setKeyVisibility(!keyVilibleItem.isSelected());
            }
        });
        addUserItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                try {
                    addUser.showCreateUserDialog();
                } catch (IOException e2) {
                    e2.printStackTrace();
                } catch (JSONException e2) {
                    e2.printStackTrace();
                } catch (NumberFormatException e1) {
                    e1.printStackTrace();
                } catch (ParameterNotSetException e1) {
                    e1.printStackTrace();
                }
            }
        });
        JMenuItem removeUserItem = new JMenuItem("Remove User");
        removeUserItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                try {
                    removeUser.showRemoveUserDialog();
                } catch (NumberFormatException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (JSONException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ParameterNotSetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });
        fileMenu.add(addUserItem);
        // fileMenu.add(removeUserItem);
        fileMenu.add(keyVilibleItem);
        bar.add(fileMenu);
        setJMenuBar(bar);
    }

    public static void main(String[] args) throws IOException, JSONException,
            ParameterNotSetException, ClassNotFoundException, InstantiationException,
            IllegalAccessException, UnsupportedLookAndFeelException {
        for (LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
            if (laf.getName().equals("Nimbus")) {
                UIManager.setLookAndFeel(laf.getClassName());
                break;
            }
        }
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    new MainFrame();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                } catch (ParameterNotSetException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    private class RemoveUserDialog extends JDialog {
        private boolean okPressed;

        private JList userList;
        private JLabel label;
        private JButton ok;

        private RemoveUserDialog(JFrame parent) throws IOException, JSONException {
            super(parent);
            setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
            JPanel mainPane = new JPanel();
            label = new JLabel("User Site and ID: ");
            userList = new JList(new DefaultListModel());
            userList.setPreferredSize(new Dimension(200, 200));
            ok = new JButton("Ok");
            ok.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    okPressed = true;
                    setVisible(false);
                }
            });
            mainPane.add(label);
            mainPane.add(userList);
            mainPane.add(ok);
            add(mainPane);
            setModal(true);
            pack();
        }

        @Override
        public void setVisible(boolean arg0) {
            Map<String, User> users = repGraph.getUsers();
            userList.setListData(users.keySet().toArray());
            super.setVisible(arg0);
        }

        private void showRemoveUserDialog() throws NumberFormatException, JSONException,
                IOException, ParameterNotSetException {
            okPressed = false;
            setVisible(true);
            if (okPressed) {
            }
        }
    }

    private class AddUserDialog extends JDialog {

        private boolean okPressed;

        private JComboBox sites;
        private JLabel label;
        private JTextField id;
        private JButton ok;

        private JList searchResults;
        private JTextField searchBox;

        private List<User> resultList;

        private AddUserDialog(JFrame parent) throws IOException, JSONException {
            super(parent);
            setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);
            JPanel mainPane = new JPanel();
            sites = new JComboBox();
            label = new JLabel("User ID: ");
            id = new JTextField(8);
            id.addKeyListener(enterPressed);
            sites.addKeyListener(enterPressed);
            ok = new JButton("Ok");
            ok.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent arg0) {
                    okPressed = true;
                    setVisible(false);
                }
            });
            searchResults = new JList();
            searchResults.setCellRenderer(new UserListCellRenderer());
            searchBox = new JTextField(20);
            searchResults.setPreferredSize(new Dimension(120, 160));
            searchBox.addKeyListener(new KeyAdapter() {

                @Override
                public void keyTyped(KeyEvent e) {
                    new UserSearchWorker().execute();
                }
            });
            searchResults.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            searchResults.addListSelectionListener(new ListSelectionListener() {
                @Override
                public void valueChanged(ListSelectionEvent e) {
                    if (!e.getValueIsAdjusting())
                        id.setText(resultList.get(searchResults.getSelectedIndex()).getId() + "");
                }
            });
            mainPane.add(sites);
            mainPane.add(label);
            mainPane.add(id);
            mainPane.add(ok);
            mainPane.add(searchResults);
            mainPane.add(searchBox);
            add(mainPane);
            setPreferredSize(new Dimension(550, 260));
            setModal(true);
            for (String s : new StackWrapDataAccess().getAllSites()) {
                sites.addItem(s);
            }
            pack();
        }

        private void showCreateUserDialog() throws NumberFormatException, JSONException,
                IOException, ParameterNotSetException {
            okPressed = false;
            setVisible(true);
            if (okPressed)
                repGraph
                        .addUser(sites.getSelectedItem().toString(), Integer.parseInt(id.getText()));
        }

        private KeyListener enterPressed = new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                if (e.getKeyChar() == '\n') {
                    ok.doClick();
                }
            }
        };

        class UserSearchWorker extends SwingWorker<List<User>, Void> {

            @Override
            protected List<User> doInBackground() throws Exception {
                return new StackWrapDataAccess().getUsers(searchBox.getText(), sites
                        .getSelectedItem().toString(), 5);
            }

            @Override
            protected void done() {
                try {
                    resultList = get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
                searchResults.setListData(resultList.toArray());
            }
        }
    }
}
